﻿#region System
using System;
using System.Collections.Generic;
using System.Threading;
using CF.Framework.Engine.Drawing;
using CF.Framework.Engine.Misc;
using CF.Framework.Engine.Screens;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#endregion

namespace CF.Framework.Engine
{
	public abstract class GameApp : Microsoft.Xna.Framework.Game
	{
		static public GameApp Current
		{
			get; private set; 
		}

		public GameSettings Settings { get; private set; }

		private GraphicsDeviceManager GraphicsDevice
		{
			get;
			set;
		}

		public ScreenManager ScreenManager
		{
			get;
			private set;
		}

		public GameScreen MainScreen
		{
			get;
			set;
		}

		public virtual double InitialFps
		{
			get { return 60.0F; }
		}

		public virtual int InitialScreenWidth
		{
			get { return 800; }
		}

		public virtual int InitialScreenHeight
		{
			get { return 600; }
		}

		public abstract void StartGame();

		public GameApp()
		{
			Settings = GameSettings.Load(@"Resources\Configurations\Settings.xml");

			GraphicsDevice = new GraphicsDeviceManager(this);

			//windowed
			GraphicsDevice.PreferredBackBufferWidth = InitialScreenWidth;
			GraphicsDevice.PreferredBackBufferHeight = InitialScreenHeight;
			GraphicsDevice.IsFullScreen = false;

			TargetElapsedTime = TimeSpan.FromSeconds(1 / InitialFps);
			IsFixedTimeStep = true;

			//Set window defaults. Parent game can override in constructor
			Window.AllowUserResizing = false;
			Window.ClientSizeChanged += Window_ClientSizeChanged;

			Content.RootDirectory = "Resources";

			//new-up components and add to Game.Components
			ScreenManager = new ScreenManager(this);
			Components.Add(ScreenManager);

			GameApp.Current = this;
		}

		void GameApp_Activated(object sender, EventArgs e)
		{
			
		}

		/// <summary>
		/// Allows the game to perform any initialization it needs to before starting to run.
		/// This is where it can query for any required services and load any non-graphic
		/// related content.  Calling base.Initialize will enumerate through any components
		/// and initialize them as well.
		/// </summary>
		protected override void Initialize()
		{
			GraphicsDevice.ApplyChanges();

			base.Initialize();
			this.StartGame();
		}

		protected override void BeginRun()
		{
			base.BeginRun();

			LoadFirstRunScreen();
		}

		private void LoadFirstRunScreen()
		{
			GameScreen screen = new FirstRunScreen();
			screen.Exiting += new EventHandler(screen_Exiting);

			ScreenManager.AddScreen(screen);
		}

		void screen_Exiting(object sender, EventArgs e)
		{
#if DEBUG
			LoadMainScreen();
#else
			LoadLogoScreen();
#endif			
		}

		private void LoadLogoScreen()
		{
			GameScreen screen = new StudioLogoScreen();
			screen.Exiting += new EventHandler(LogoScreen_Exiting);

			ScreenManager.AddScreen(screen);
		}

		void LogoScreen_Exiting(object sender, EventArgs e)
		{
			LoadMainScreen();
		}

		private void LoadMainScreen()
		{
			if (MainScreen != null)
			{
				ScreenManager.Clear();
				ScreenManager.AddScreen(MainScreen);
			}
		}

		protected override void Update(GameTime gameTime)
		{
			base.Update(gameTime);
		}

		/// <summary>
		/// This is called when the game should draw itself.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		protected override void Draw(GameTime gameTime)
		{
			ScreenManager.GraphicsDevice.Clear(Color.Black);

			base.Draw(gameTime);
		}

		private void Window_ClientSizeChanged(object sender, EventArgs e)
		{
			if (Window.ClientBounds.Width > 0 && Window.ClientBounds.Height > 0)
			{
				GraphicsDevice.PreferredBackBufferWidth = Window.ClientBounds.Width;
				GraphicsDevice.PreferredBackBufferHeight = Window.ClientBounds.Height;
			}
		}
	}
}
